using System;
using System.Collections;
using System.Security.Principal;
using System.Web;
using System.Reflection;
using System.Data;

using Castle.Facilities.NHibernateIntegration;
using Castle.Services.Transaction;
using NHibernate;
using NetBpm.Util.Client;
using NetBpm.Workflow.Organisation.EComp;
using NetBpm.Workflow.Organisation;
using NetBpm.Workflow.Delegation;
using NetBpm.Workflow.Definition;
using NetBpm.Workflow.Definition.EComp;
using NetBpm.Workflow.Execution;
using NetBpm.Workflow.Execution.EComp;
using NetBpm.Workflow.Definition.Attr;
using NetBpm.Workflow.Log.EComp;

using BEGDC.Utility.ExceptionManagement;
using BEGDC.CC.BL.Workflow;
using BEGDC.CC.BL.Common;
using BEGDC.Utility.Castle;
using BEGDC.CC.Entity;
using BEGDC.CC.BL.CCFlow.CR;

namespace BEGDC.CC.BL.CCFlow
{
	/// <summary>
	/// Summary description for FlowBase.
	/// </summary>
	public class FlowBase
	{

		protected const string NEXT_TRANSITION = "NextTransition";
//		protected Application applicationObject = null;

		public FlowBase()
		{
			//
			// TODO: Add constructor logic here
			//
		}


		protected virtual string ProjectType
		{
			get
			{
				throw new Exception("ProjectType should be implemented");
			}
		}

		#region Workflow operations

		public virtual long Start()
		{
			IExecutionSessionLocal executionComponent = null;
			try
			{
				long processDefinitionID = BEGDC.CC.BL.Workflow.Configuration.GetProcessDefinitionID(this.ProjectType);
				executionComponent = ServiceLocator.Instance.GetService(typeof (IExecutionSessionLocal)) as IExecutionSessionLocal;
				IProcessInstance processInstance = executionComponent.StartProcessInstance(processDefinitionID);
				return processInstance.RootFlow.Id;
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new Exception("Start Process error.", ex);
			}
			finally
			{
				ServiceLocator.Instance.Release(executionComponent);
			}
		}
		


//		public void Perform(long flowId, string nextTransition, string comment)
//		{
//			IDictionary attributes = new Hashtable();				
//			attributes.Add(NEXT_TRANSITION, nextTransition);
//			this.Perform(flowId, attributes, comment);
//		}

		public void Perform(ISession session, long flowId, string nextTransition, string comment)
		{
			IDictionary attributes = new Hashtable();				
			attributes.Add(NEXT_TRANSITION, nextTransition);
			this.Perform(session, flowId, attributes, comment);
		}

        public void Perform(ISession session, long flowId, string nextTransition, string source, FlowMember member, string comment)
        {
            IDictionary attributes = new Hashtable();
            attributes.Add(NEXT_TRANSITION, nextTransition);
            this.Perform(session, flowId, attributes, source, member, comment);
        }

		public void Drawback(ISession session, long flowId, string comment)
		{
			IExecutionSessionLocal executionComponent = null;
			try
			{
				executionComponent = ServiceLocator.Instance.GetService(typeof (IExecutionSessionLocal)) as IExecutionSessionLocal;	
				FlowInstance instance = this.QueryFlowInstance(session, flowId);
				string source = instance.CurrentStep.StepName;
				int appId = instance.Application.Id;

				IList flows = null;
				flows = executionComponent.DrawbackActivity(flowId, null, null);

				if (flows.Count > 0)
				{
					IFlow flow = (IFlow)flows[0];
					string nextStep = flow.Node.Name;
					string owner = this.GetWorkflowStepEmployee(session, flowId, nextStep);
					if(owner == string.Empty)
					{
						Type curtype = flow.Node.GetType();
						Type endtype = typeof(NetBpm.Workflow.Definition.Impl.EndStateImpl);
						if (curtype.Equals(endtype) || curtype.IsSubclassOf(endtype))
							owner = "N/A";
						else
							owner = flow.GetActor().Name;
					}

					//Update FlowInstance
					if(instance.Application.ApplicationType==WorkflowTypes.CO)
					{
						CRFlow crflow = (CRFlow)this;
						crflow.IsInShanghai = false;
						crflow.SaveActionLog(session, appId, BEGDC.CC.BL.Workflow.Action.Drawback, source, nextStep, comment);
						crflow.UpdateFlowInstance(session, flowId, nextStep, nextStep, SysDicItem.ProjectStatusFlag.NORMAL, owner, owner);
					}
					else
					{
						this.SaveActionLog(session, appId, BEGDC.CC.BL.Workflow.Action.Drawback, source, nextStep, comment);
						this.UpdateFlowInstance(session, flowId, nextStep, nextStep, SysDicItem.ProjectStatusFlag.NORMAL, owner, owner);
					}
					
				}
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
				ServiceLocator.Instance.Release(executionComponent);
			}
		}

		public void ReplyInquiry(ISession session, long flowId, string comment)
		{
			IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
			FlowInstance instance = this.QueryFlowInstance(session, flowId);
			string source = instance.CurrentStep.StepName;
			int appId = instance.Application.Id;
			int stateId = utiService.QueryStateByCode(SysDicItem.ProjectStatusFlag.NORMAL).Id;
			
			string query = "update flowinstance set currentactivestep=currentstep,currentactiveowner=currentowner,state="+stateId+" where FlowID ="+flowId;
			BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
			this.SaveActionLog(session, appId, BEGDC.CC.BL.Workflow.Action.ReplyQuery, source, source, comment);

			//Alan 2007/08/09 for Reply email
			BEGDC.CC.BL.Email.IEmail email = AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.EmailService] as BEGDC.CC.BL.Email.IEmail;
			email.Send(flowId, "ReplyQuery");
		}

		public void Suspend(ISession session, long flowId, string comment)
		{
			IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
			FlowInstance instance = this.QueryFlowInstance(session, flowId);
			string source = instance.CurrentStep.StepName;
			int appId = instance.Application.Id;
			int stateId = utiService.QueryStateByCode(SysDicItem.ProjectStatusFlag.Pending).Id;
			
			string query = "update flowinstance set state="+stateId+" where FlowID ="+flowId;
			BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
			this.SaveActionLog(session, appId, BEGDC.CC.BL.Workflow.Action.Suspend, source, source, comment);
		}

		public void Resume(ISession session, long flowId, string comment)
		{
			IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
			FlowInstance instance = this.QueryFlowInstance(session, flowId);
			string source = instance.CurrentStep.StepName;
			int appId = instance.Application.Id;
			int stateId = utiService.QueryStateByCode(SysDicItem.ProjectStatusFlag.Resume).Id;
			
			string query = "update flowinstance set state="+stateId+" where FlowID ="+flowId;
			BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
			this.SaveActionLog(session, appId, BEGDC.CC.BL.Workflow.Action.Resume, source, source, comment);
		}

		public void Archive(ISession session, long flowId)
		{
			IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
			FlowInstance instance = this.QueryFlowInstance(session, flowId);
			string source = SysDicItem.ProjectStatusFlag.End;
			int appId = instance.Application.Id;
			int stateId = utiService.QueryStateByCode(SysDicItem.ProjectStatusFlag.Archive).Id;
			
			string query = "update flowinstance set state="+stateId+" where FlowID ="+flowId;
			BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
			this.SaveActionLog(session, appId, BEGDC.CC.BL.Workflow.Action.Archive, source, source, string.Empty);
		}

		public void Reset(int appID, long flowId)
		{
		}

		public void Callback(ISession session, long flowId, string comment)
		{
//			IExecutionSessionLocal executionComponent = null;
			try
			{
				IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
				FlowInstance instance = this.QueryFlowInstance(session, flowId);
//				this.applicationObject = instance.Application;
				string source = instance.CurrentStep.StepName;
				int typeId = utiService.GetDicItemID(instance.Application.ApplicationType, BEGDC.CC.BL.Common.DicType.Application_Type);
				int appId = instance.Application.Id;
				int stateId = utiService.QueryStateByCode(SysDicItem.ProjectStatusFlag.CALLBACK).Id;
				
				string step = string.Empty;
				if(instance.Application.ApplicationType == WorkflowTypes.CV)
				{
					if(instance.CurrentStep.StepCode == WorkTransition.CV_Apply || instance.CurrentStep.StepCode == WorkTransition.CV_Assignment)
						step = WorkTransition.CV_Apply;
					else
						step = WorkTransition.CV_ReApply;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.CR)
				{
					if(instance.CurrentStep.StepCode == WorkTransition.CR_Request || instance.CurrentStep.StepCode == WorkTransition.CR_AssignApp)
						step = WorkTransition.CR_Request;
					else
						step = WorkTransition.CR_ReRequest;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.OCR)
				{
					if(instance.CurrentStep.StepCode == WorkTransition.OCR_Request || instance.CurrentStep.StepCode == WorkTransition.OCR_AssignApp)
						step = WorkTransition.OCR_Request;
					else
						step = WorkTransition.OCR_ReRequest;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.EBD)
				{
					if(instance.CurrentStep.StepCode == WorkTransition.EBD_Request || instance.CurrentStep.StepCode == WorkTransition.EBD_AssignApp)
						step = WorkTransition.EBD_Request;
					else
						step = WorkTransition.EBD_ReRequest;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.ESC)
				{
					if(instance.CurrentStep.StepCode == WorkTransition.ESC_Request || instance.CurrentStep.StepCode == WorkTransition.ESC_AssignApp)
						step = WorkTransition.ESC_Request;
					else
						step = WorkTransition.ESC_ReRequest;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.EV)
					step = WorkTransition.EV_Request;
				else if(instance.Application.ApplicationType == WorkflowTypes.CO)
				{
					if(instance.CurrentStep.StepCode == WorkTransition.CO_Request || instance.CurrentStep.StepCode == WorkTransition.CO_AssignApp)
						step = WorkTransition.CO_Request;
					else
						step = WorkTransition.CO_ReRequest;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.AP)
					step = WorkTransition.AP_Request;
				if(instance.Application.ApplicationType == WorkflowTypes.OCV)
				{
					if(instance.CurrentStep.StepCode == WorkTransition.OCV_Apply || instance.CurrentStep.StepCode == WorkTransition.OCV_Assignment)
						step = WorkTransition.OCV_Apply;
					else
						step = WorkTransition.OCV_ReApply;
				}
				if(instance.Application.ApplicationType == WorkflowTypes.EBDCV)
				{
					if(instance.CurrentStep.StepCode == WorkTransition.EBDCV_Apply || instance.CurrentStep.StepCode == WorkTransition.EBDCV_Assignment)
						step = WorkTransition.EBDCV_Apply;
					else
						step = WorkTransition.EBDCV_ReApply;
				}
				if(instance.Application.ApplicationType == WorkflowTypes.ESCCV)
				{
					if(instance.CurrentStep.StepCode == WorkTransition.ESCCV_Apply || instance.CurrentStep.StepCode == WorkTransition.ESCCV_Assignment)
						step = WorkTransition.ESCCV_Apply;
					else
						step = WorkTransition.ESCCV_ReApply;
				}
				int stepid = utiService.QueryStepByCode(step, typeId).Id;
				
				IExecute exe = AppContainer.Instance[ServiceConst.ExecuteService] as IExecute;;		
				exe.MoveFlowState(flowId, step, instance.Application.ApplicationType);
				string actor = this.GetWorkflowStepEmployee(session, flowId, step);

				string query = "update flowinstance set state="+stateId+", currentstep="+stepid+",currentactivestep="+stepid
					+",CurrentOwner='"+actor+"',CurrentActiveOwner='"+actor+"' where FlowID ="+flowId;
				BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
				this.SaveActionLog(session, appId, BEGDC.CC.BL.Workflow.Action.Callback, source, source, comment);

			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new Exception("Execute flow("+flowId.ToString()+") error.", ex);
			}
			finally
			{
//				ServiceLocator.Instance.Release(executionComponent);
			}
			
		}

		public void Cancel(ISession session, long flowId, string comment)
		{
			IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
			FlowInstance instance = this.QueryFlowInstance(session, flowId);
			string source = instance.CurrentStep.StepName;
			int appId = instance.Application.Id;
			int stateId = utiService.QueryStateByCode(SysDicItem.ProjectStatusFlag.CANCEL).Id;
			
			string query = "update flowinstance set state="+stateId+" where FlowID ="+flowId;
			BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
			this.SaveActionLog(session, appId, BEGDC.CC.BL.Workflow.Action.Cancel, source, source, comment);
		}

		

		/// <summary>
		/// Do Step
		/// </summary>
		/// <param name="flowID"></param>
		/// <param name="attributes"></param>
//		private void Perform(long flowID, IDictionary attributes)
//		{
//			IExecutionSessionLocal executionComponent = null;
//			try
//			{
//				executionComponent = ServiceLocator.Instance.GetService(typeof (IExecutionSessionLocal)) as IExecutionSessionLocal;	
//				
//				
//				IList flows = null;
//				if (attributes != null)
//				{
//					flows = executionComponent.PerformActivity(flowID, attributes);
//				}
//				else
//					flows = executionComponent.PerformActivity(flowID);
//			}
//			catch(Exception ex)
//			{
//				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new Exception("Execute flow("+flowID.ToString()+") error.", ex);
//			}
//			finally
//			{
//				ServiceLocator.Instance.Release(executionComponent);
//			}
//		}

		/// <summary>
		/// Do step and update flowInstance information
		/// </summary>
		/// <param name="session"></param>
		/// <param name="flowId"></param>
		/// <param name="attributes"></param>
		[Transaction(TransactionMode.Requires)]
		private void Perform(ISession session, long flowId, IDictionary attributes, string comment)
		{
			IExecutionSessionLocal executionComponent = null;
			try
			{
				executionComponent = ServiceLocator.Instance.GetService(typeof (IExecutionSessionLocal)) as IExecutionSessionLocal;	
				FlowInstance instance = this.QueryFlowInstance(session, flowId);
				//				this.applicationObject = instance.Application;
				string state = SysDicItem.ProjectStatusFlag.NORMAL;
				string source = instance.CurrentStep.StepName;
				int appId = instance.Application.Id;

				IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
				int typeId = utiService.GetDicItemID(instance.Application.ApplicationType, BEGDC.CC.BL.Common.DicType.Application_Type);
				int stepId = utiService.QueryStepByCode(source, typeId).Id;
				FlowMember member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
                if(member != null)
				{
					member.Employee = new Employee();
					member.Employee.Id = ((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id;
					session.Update( member, member.Id );
				}

				string rerequest = string.Empty;
				string feedback = string.Empty;
				string depHead = string.Empty;
				if(instance.Application.ApplicationType == WorkflowTypes.CV && source == WorkTransition.CV_Apply)
				{
					rerequest = WorkTransition.CV_ReApply;
					feedback = WorkTransition.CV_Feedback;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.CR && source == WorkTransition.CR_Request)
				{
					rerequest = WorkTransition.CR_ReRequest;
					feedback = WorkTransition.CR_CRSurvey;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.EV && source == WorkTransition.EV_Request)
				{
					rerequest = WorkTransition.EV_ReRequest;
					feedback = WorkTransition.EV_MeetingMinutes;
				}
				else if(source == WorkTransition.CO_Request)
				{
					rerequest = WorkTransition.CO_ReRequest;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.OCV && (source == WorkTransition.OCV_Apply
					|| source == WorkTransition.OCV_ReApply))
				{
					rerequest = WorkTransition.OCV_ReApply;
					feedback = WorkTransition.OCV_OCVSurvey;

                    //if(instance.Application.IsSSME)
                    //    depHead = this.GetDepartmentHeadByCostCenter(session, instance.Application.CostCenterCode.DicItemKey);
                    //else
                    //    depHead = this.GetDepartmentHeadByDepartment(session, instance.Application.DepartmentType.DicItemKey);
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.EBDCV && (source == WorkTransition.EBDCV_Apply
					|| source == WorkTransition.EBDCV_ReApply))
				{
					rerequest = WorkTransition.EBDCV_ReApply;
					feedback = WorkTransition.EBDCV_EBDCVSurvey;

                    if (instance.Application.IsSSME)
                        depHead = this.GetDepartmentHeadByCostCenter(session, instance.Application.CostCenterCode.DicItemKey);
                    else
                        depHead = this.GetDepartmentHeadByDepartment(session, instance.Application.DepartmentType.DicItemKey);
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.ESCCV && (source == WorkTransition.ESCCV_Apply
					|| source == WorkTransition.ESCCV_ReApply))
				{
					rerequest = WorkTransition.ESCCV_ReApply;
					feedback = WorkTransition.ESCCV_ESCCVSurvey;

					if(instance.Application.IsSSME)
						depHead = this.GetDepartmentHeadByCostCenter(session, instance.Application.CostCenterCode.DicItemKey);
					else
						depHead = this.GetDepartmentHeadByDepartment(session, instance.Application.DepartmentType.DicItemKey);
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.OCR && (source == WorkTransition.OCR_Request
					|| source == WorkTransition.OCR_ReRequest))
				{
					rerequest = WorkTransition.OCR_ReRequest;
					feedback = WorkTransition.OCR_OCRSurvey;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.EBD && (source == WorkTransition.EBD_Request
					|| source == WorkTransition.EBD_ReRequest))
				{
					rerequest = WorkTransition.EBD_ReRequest;
					feedback = WorkTransition.EBD_EBDSurvey;
				}
				else if(instance.Application.ApplicationType == WorkflowTypes.ESC && (source == WorkTransition.ESC_Request
					|| source == WorkTransition.ESC_ReRequest))
				{
					rerequest = WorkTransition.ESC_ReRequest;
					feedback = WorkTransition.ESC_ESCSurvey;
				}
				// Update the actor to memberlist
				if(source == string.Empty)
				{
					stepId = utiService.QueryStepByCode(source, typeId).Id;
					member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
					if(member != null)
					{
						member.Employee = new Employee();
						member.Employee.Id = ((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id;
						session.Update( member, member.Id );
					}
				}
				
				if(rerequest != string.Empty)
				{
					stepId = utiService.QueryStepByCode(rerequest, typeId).Id;
					member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
					if(member != null)
					{
						member.Employee = new Employee();
						member.Employee.Id = ((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id;
						session.Update( member, member.Id );
					}
				}
				if(feedback != string.Empty)
				{
					stepId = utiService.QueryStepByCode(feedback, typeId).Id;
					member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
					if(member != null)
					{
						member.Employee = new Employee();
						member.Employee.Id = ((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id;
						session.Update( member, member.Id );
					}
				}
				if(depHead != string.Empty)
				{
					if(instance.Application.ApplicationType == WorkflowTypes.OCV)
					{
						stepId = utiService.QueryStepByCode(WorkTransition.OCV_DepartmentHeadApproval, typeId).Id;
						member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
						if(member != null)
						{
							member.Employee = new Employee();
							member.Employee.Id = depHead;
							session.Update( member, member.Id );
						}

						stepId = utiService.QueryStepByCode(WorkTransition.OCV_DepartmentVPApproval, typeId).Id;
						member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
						if(member != null)
						{
							member.Employee = new Employee();
							member.Employee.Id = depHead;
							session.Update( member, member.Id );
						}
					}
				}

				IList flows = null;
				if (attributes != null)
				{
					flows = executionComponent.PerformActivity(flowId, attributes);
				}
				else
					flows = executionComponent.PerformActivity(flowId);

				string nextStep = BEGDC.CC.BL.Workflow.WorkTransition.End;
				string owner = "N/A";
				
				if (flows.Count > 0)
				{
					IFlow flow = (IFlow)flows[0];
					nextStep = flow.Node.Name;
					owner = this.GetWorkflowStepEmployee(session, flowId, nextStep);
					if(owner == string.Empty)
					{
						Type curtype = flow.Node.GetType();
						Type endtype = typeof(NetBpm.Workflow.Definition.Impl.EndStateImpl);
						if (curtype.Equals(endtype) || curtype.IsSubclassOf(endtype))
						{
							owner = "N/A";
							state = SysDicItem.ProjectStatusFlag.Closed;
						}
						else
							owner = flow.GetActor().Name;
					}
				}
				
				string nextTransition = attributes[NEXT_TRANSITION].ToString();
				
				if(nextTransition == WorkTransition.Reject)
				{
					nextTransition = BEGDC.CC.BL.Workflow.Action.Reject;
					state = SysDicItem.ProjectStatusFlag.Reject;
				}
				else
				{
					//nextTransition = BEGDC.CC.BL.Workflow.Action.Submit;
				}
				if(owner == "N/A")
					state = SysDicItem.ProjectStatusFlag.Closed;
				this.SaveActionLog(session, appId, nextTransition, source, nextStep, comment);
				this.UpdateFlowInstance(session, flowId, nextStep, nextStep, state, owner, owner);
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new Exception("Execute flow("+flowId.ToString()+") error.", ex);
			}
			finally
			{
				ServiceLocator.Instance.Release(executionComponent);
			}
		}

        /// <summary>
        /// Do step and update flowInstance information
        /// </summary>
        /// <param name="session"></param>
        /// <param name="flowId"></param>
        /// <param name="attributes"></param>
        [Transaction(TransactionMode.Requires)]
        private void Perform(ISession session, long flowId, IDictionary attributes,string source, FlowMember member, string comment)
        {
            IExecutionSessionLocal executionComponent = null;
            try
            {
                executionComponent = ServiceLocator.Instance.GetService(typeof(IExecutionSessionLocal)) as IExecutionSessionLocal;
                FlowInstance instance = this.QueryFlowInstance(session, flowId);
                string state = SysDicItem.ProjectStatusFlag.NORMAL;
                int appId = instance.Application.Id;
                IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
                int typeId = utiService.GetDicItemID(instance.Application.ApplicationType, BEGDC.CC.BL.Common.DicType.Application_Type);
                int stepId = utiService.QueryStepByCode(source, typeId).Id;
  
                string rerequest = string.Empty;
                string feedback = string.Empty;
                string depHead = string.Empty;

                if (instance.Application.ApplicationType == WorkflowTypes.OCV && (source == WorkTransition.OCV_Apply
                    || source == WorkTransition.OCV_ReApply))
                {
                    rerequest = WorkTransition.OCV_ReApply;
                    feedback = WorkTransition.OCV_OCVSurvey;

                    //if (instance.Application.IsSSME)
                    //    depHead = this.GetDepartmentHeadByCostCenter(session, instance.Application.CostCenterCode.DicItemKey);
                    //else
                    //    depHead = this.GetDepartmentHeadByDepartment(session, instance.Application.DepartmentType.DicItemKey);
                }
                else if (instance.Application.ApplicationType == WorkflowTypes.OCR && (source == WorkTransition.OCR_Request
                    || source == WorkTransition.OCR_ReRequest))
                {
                    rerequest = WorkTransition.OCR_ReRequest;
                    feedback = WorkTransition.OCR_OCRSurvey;
                }

                // Update the actor to memberlist
                if (source == string.Empty)
                {
                    stepId = utiService.QueryStepByCode(source, typeId).Id;
                    member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
                    if (member != null)
                    {
                        member.Employee = new Employee();
                        member.Employee.Id = ((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id;
                        session.Update(member, member.Id);
                    }
                }

                if (rerequest != string.Empty)
                {
                    stepId = utiService.QueryStepByCode(rerequest, typeId).Id;
                    member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
                    if (member != null)
                    {
                        member.Employee = new Employee();
                        member.Employee.Id = ((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id;
                        session.Update(member, member.Id);
                    }
                }
                if (feedback != string.Empty)
                {
                    stepId = utiService.QueryStepByCode(feedback, typeId).Id;
                    member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
                    if (member != null)
                    {
                        member.Employee = new Employee();
                        member.Employee.Id = ((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id;
                        session.Update(member, member.Id);
                    }
                }
                if (depHead != string.Empty)
                {
                    if (instance.Application.ApplicationType == WorkflowTypes.OCV)
                    {
                        stepId = utiService.QueryStepByCode(WorkTransition.OCV_DepartmentHeadApproval, typeId).Id;
                        member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
                        if (member != null)
                        {
                            member.Employee = new Employee();
                            member.Employee.Id = depHead;
                            session.Update(member, member.Id);
                        }

                        stepId = utiService.QueryStepByCode(WorkTransition.OCV_DepartmentVPApproval, typeId).Id;
                        member = this.GetFlowMemberByAppStep(session, instance.Application.Id, stepId);
                        if (member != null)
                        {
                            member.Employee = new Employee();
                            member.Employee.Id = depHead;
                            session.Update(member, member.Id);
                        }
                    }
                }

                IList flows = null;
                if (attributes != null)
                {
                    flows = executionComponent.PerformActivity(flowId, attributes);
                }
                else
                    flows = executionComponent.PerformActivity(flowId);

                string nextStep = BEGDC.CC.BL.Workflow.WorkTransition.End;
                string owner = "N/A";

                if (flows.Count > 0)
                {
                    IFlow flow = (IFlow)flows[0];
                    nextStep = flow.Node.Name;
                    owner = this.GetWorkflowStepEmployee(session, flowId, nextStep);
                    if (owner == string.Empty)
                    {
                        Type curtype = flow.Node.GetType();
                        Type endtype = typeof(NetBpm.Workflow.Definition.Impl.EndStateImpl);
                        if (curtype.Equals(endtype) || curtype.IsSubclassOf(endtype))
                        {
                            owner = "N/A";
                            state = SysDicItem.ProjectStatusFlag.Closed;
                        }
                        else
                            owner = flow.GetActor().Name;
                    }
                }

                string nextTransition = attributes[NEXT_TRANSITION].ToString();

                if (nextTransition == WorkTransition.Reject)
                {
                    nextTransition = BEGDC.CC.BL.Workflow.Action.Reject;
                    state = SysDicItem.ProjectStatusFlag.Reject;
                }
                else
                {
                    //nextTransition = BEGDC.CC.BL.Workflow.Action.Submit;
                }
                if (owner == "N/A")
                    state = SysDicItem.ProjectStatusFlag.Closed;

                if (member.Employee != null)
                {
                    this.SaveActionLog(session, appId, nextTransition, source, nextStep, member ,comment);
                }
                else
                {
                    this.SaveActionLog(session, appId, nextTransition, source, nextStep, comment);
                }
                this.UpdateFlowInstance(session, flowId, nextStep, nextStep, state, owner, owner);
            }
            catch (Exception ex)
            {
                CCS.Utility.LogAccess.WriteErrLog(ex.StackTrace, ex.Message); throw new Exception("Execute flow(" + flowId.ToString() + ") error.", ex);
            }
            finally
            {
                ServiceLocator.Instance.Release(executionComponent);
            }
        }

		private void UpdateFlowInstance(ISession session, long flowID, string currentStep, string activeStep, string state, string actor, string activeActor)
		{
			try
			{
				IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
				Common.Query.IQuery queryService = AppContainer.Instance[ServiceConst.QueryService] as Common.Query.IQuery;
				Entity.FlowInstance instance = queryService.QueryFlowInstanceByFlowId( (int)flowID );

				int stateId = utiService.QueryStateByCode(state).Id;
				int typeId = utiService.GetDicItemID(instance.Application.ApplicationType, BEGDC.CC.BL.Common.DicType.Application_Type);
				int stepId = utiService.QueryStepByCode(currentStep, typeId).Id;
				int activestepId = utiService.QueryStepByCode(activeStep, typeId).Id;
			
				string query = "Update FlowInstance set State="+stateId+",CurrentStep="+stepId+",CurrentActiveStep="+activestepId
					+",CurrentOwner='"+actor+"', CurrentActiveOwner='"+activeActor+"', LastModifiedDate='"+System.DateTime.Now.ToString()+"'"
					+" where FlowID ="+flowID;
				BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
		}

		public void Query(ISession session, Application app, string activeStep, string state, string comment)
		{
			long flowId = 0;
			if( app != null )
			{
				BEGDC.CC.BL.Common.Query.IQuery queryService= BEGDC.Utility.Castle.AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.QueryService] as BEGDC.CC.BL.Common.Query.IQuery;
				flowId = queryService.QueryFlowInstance(app.Id).FlowID;

				this.Query( session, flowId, activeStep, state, comment);
			}
		}

		public void Query(ISession session, long flowID, string activeStep, string state, string comment)
		{
			try
			{
				IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
				FlowInstance instance = this.QueryFlowInstance(session, flowID);
				string source = instance.CurrentStep.StepName;
				int appId = instance.Application.Id;

				int stateId = utiService.QueryStateByCode(state).Id;
				int typeId = utiService.GetDicItemID(this.ProjectType, BEGDC.CC.BL.Common.DicType.Application_Type);
				int activestepId = utiService.QueryStepByCode(activeStep, typeId).Id;
				string owner = this.GetWorkflowStepEmployee(session, flowID, activeStep);
				if (owner == string.Empty)
					owner = this.GetWorkflowStepRole(session, flowID, activeStep);

				// Update the actor to memberlist
				if(source == string.Empty)
				{
					int stepId = utiService.QueryStepByCode(source, typeId).Id;
					FlowMember member = this.GetFlowMemberByAppStep(session, appId, stepId);
					if(member != null)
					{
						member.Employee = new Employee();
						member.Employee.Id = ((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id;
						session.Update( member, member.Id );
					}
				}

			
				string query = "Update FlowInstance set State="+stateId+",CurrentActiveStep="+activestepId+",CurrentActiveOwner='"+owner
					+"', CurrentOwner='"+((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id+"' where FlowID ="+flowID;
				BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
				this.SaveActionLog(session, appId, BEGDC.CC.BL.Workflow.Action.Query, source, activeStep, comment);

				//Alan 2007/8/9 for Query email
				BEGDC.CC.BL.Email.IEmail email = AppContainer.Instance[ServiceConst.EmailService] as BEGDC.CC.BL.Email.IEmail;
				email.Send(flowID, "Query");

			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
		}

		public void InitializeProjectMember(ISession session, int appId)
		{
			try
			{
				IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
				int typeId = utiService.GetDicItemID(this.ProjectType, BEGDC.CC.BL.Common.DicType.Application_Type);
				string query = "select * from AssignmentDefination where ProjectType = "+typeId.ToString();
				DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, query);

				for(int i=0; i<table.Rows.Count; i++)
				{
					FlowMember fm = new FlowMember();
					fm.Application = new Application();
					fm.Application.Id = appId;
					fm.Role = new Role();
					fm.Role.Id = Convert.ToInt32(table.Rows[i]["RoleId"]);
					fm.Step = new Step();
					fm.Step.Id = Convert.ToInt32(table.Rows[i]["StepId"]);
					session.Save(fm);
				}
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
		}

		public void UpdateProjectMember(ISession session, int appId, string cat)
		{
			try
			{
				//IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
				//int typeId = utiService.GetDicItemID(this.ProjectType, BEGDC.CC.BL.Common.DicType.Application_Type);
				string query = "select FlowMemberID from Flowmember inner join [role] on flowmember.roleid = role.roleid "
					+" where role.rolename in('"+BEGDC.CC.BL.Workflow.UserRole.CATDirector+"','"+BEGDC.CC.BL.Workflow.UserRole.PSO
					+"') and flowmember.appid="+appId;
				DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, query);

				if(table != null && table.Rows.Count > 0)
				{
					query = "update flowmember set EmployeeNo = '"+cat+"'where FlowMemberID="+table.Rows[0][0].ToString();

					BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
				}
				if(table != null && table.Rows.Count > 1)
				{
					query = "update flowmember set EmployeeNo = '"+cat+"'where FlowMemberID="+table.Rows[1][0].ToString();

					BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
				}
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
		}

		public void UpdateDesignatedFlowMember(ISession session, int AppID, string RoleName)
		{
			try
			{
				string query = "select ur.EmployeeNo from UserRole AS ur,Role AS r where ur.RoleID=r.RoleID and r.RoleName='"+RoleName+"'";
				DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, query);

				if(table != null && table.Rows.Count > 0)
				{
					query = "update FlowMember AS fm set fm.EmployeeNo = '"+table.Rows[0][0].ToString()+"' where AppID="+AppID+" and fm.RoleID=Role.RoleID and Role.RoleName='"+RoleName+"'";
					BEGDC.Utility.NHibernate.NHibernateUtil.ExecuteNonQuery(session, query);
				}
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="session"></param>
		/// <param name="appId"></param>
		/// <param name="stepID"></param>
		/// <returns></returns>
		public FlowMember GetFlowMemberByAppStep(ISession session, int appId, int stepID)
		{
			try
			{
				IList list = session.Find("FROM FlowMember WHERE AppID = " + appId +  " AND StepID = " + stepID);
				if( list != null && list.Count > 0 )
					return (FlowMember)list[0];
				else
					return null;
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="session"></param>
		/// <param name="appId"></param>
		/// <param name="stepName"></param>
		/// <returns></returns>
		public FlowMember GetFlowMemberByAppStep(ISession session, int appId, string stepName, FlowTypes typeName)
		{
			
			int typeID = 0;//(int)typeName + 1;
			string type = string.Empty;

			switch(typeName)
			{
				case FlowTypes.EV:
					type = WorkflowTypes.EV;
					break;
				case FlowTypes.CV:
					type = WorkflowTypes.CV;
					break;
				case FlowTypes.CR:
					type = WorkflowTypes.CR;
					break;
				case FlowTypes.CO:
					type = WorkflowTypes.CO;
					break;
				case FlowTypes.OCR:
					type = WorkflowTypes.OCR;
					break;
				case FlowTypes.OCV:
					type = WorkflowTypes.OCV;
					break;
				case FlowTypes.EBD:
					type = WorkflowTypes.EBD;
					break;
				case FlowTypes.ESC:
					type = WorkflowTypes.ESC;
					break;
				case FlowTypes.EBDCV:
					type = WorkflowTypes.EBDCV;
					break;
				case FlowTypes.ESCCV:
					type = WorkflowTypes.ESCCV;
					break;
			}
			
			IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
			typeID = utiService.GetDicItemID(type, BEGDC.CC.BL.Common.DicType.Application_Type);
			
			IList stepList = session.Find( "FROM Step WHERE StepCode='" + stepName + "' AND AppTypeID = " + typeID);
			if( stepList == null || stepList.Count == 0 )
				return null;
			else
			{
				Step step = stepList[0] as Step;
				return this.GetFlowMemberByAppStep( session, appId, step.Id);
			}
			
		}

		private string GetWorkflowStepEmployee(ISession session, long flowID, string stepName)
		{
			string query = "select isnull(fm.employeeno,'') from application a inner join flowinstance f on a.appid = f.appid"
				+" inner join dicitem d on d.dicitemkey = a.applicationtype inner join step s on s.apptypeid = d.dicitemid and s.stepcode = '"
				+stepName+"' inner join flowmember fm on fm.appid = a.appid and fm.stepid = s.stepid where f.flowid="+flowID;
			DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, query);
			if(table != null && table.Rows.Count > 0)
				return table.Rows[0][0].ToString();
			return string.Empty;
		}

		private string GetWorkflowStepRole(ISession session, long flowID, string stepName)
		{
			string query = "select isnull(r.roleName,'') from application a inner join flowinstance f on a.appid = f.appid"
				+" inner join dicitem d on d.dicitemkey = a.applicationtype inner join step s on s.apptypeid = d.dicitemid and s.stepcode = '"
				+stepName+"' inner join flowmember fm on fm.appid = a.appid and fm.stepid = s.stepid "
				+" inner join Role r on fm.roleID = r.roleID where f.flowid="+flowID;
			DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, query);
			if(table != null && table.Rows.Count > 0)
				return table.Rows[0][0].ToString();
			return string.Empty;
		}

		#endregion


		#region Business object operations

		public void Save(ISession session, object obj )
		{
			if( obj == null )
				throw new GDCException(BEGDC.CC.BL.Common.ErrorCode.NoInstance_Exception, "No instance to Save");
			try
			{
				if( session.IsOpen )
				{
					session.Save( obj );
				}
				else
				{
					throw new GDCException( BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Session is closed");
				}
			}
			catch( Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new GDCException(BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Failed to save application infomation", ex);
			}
		}
		/// <summary>
		/// 
		/// </summary>
		/// <param name="session"></param>
		/// <param name="obj"></param>
		public void Update(ISession session, object obj, object id)
		{
			if( obj == null )
				throw new GDCException(BEGDC.CC.BL.Common.ErrorCode.NoInstance_Exception, "No instance to Save");
			try
			{
				if( session.IsOpen )
				{
					session.Update( obj, id);
				}
				else
				{
					throw new GDCException( BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Session is closed");
				}
				session.Flush();
			}
			catch( Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new GDCException(BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Failed to save application infomation", ex);
			}
		}
		/// <summary>
		/// Save or Update an application information
		/// </summary>
		/// <param name="session"></param>
		/// <param name="app">instance to save</param>
		public void SaveApplication( ISession session, Application app )
		{
			if( app == null )
				throw new GDCException(BEGDC.CC.BL.Common.ErrorCode.NoInstance_Exception, "No instance to Save");

			try
			{
				if( session.IsOpen )
				{
					session.SaveOrUpdate( app );
				}
				else
				{
					throw new GDCException( BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Session is closed");
				}
			}
			catch( Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new GDCException(BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Failed to save application infomation", ex);
			}
		}

		/// <summary>
		/// Save operation log
		/// </summary>
		/// <param name="session"></param>
		/// <param name="log"></param>
		public void SaveActionLog(ISession session, ActionLog log)
		{
			if( log == null )
				return;
			try
			{
				if( session.IsOpen )
				{
					session.Save( log );
				}
				else
				{
					throw new GDCException( BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Session is closed");
				}
			}
			catch( Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new GDCException(BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Failed to save log infomation");
			}
		}

		public void SaveFlowMember(ISession session, FlowMember flowMember)
		{
			if( flowMember == null )
				return;
			try
			{
				if( session.IsOpen )
				{
					session.Save( flowMember );
				}
				else
				{
					throw new GDCException( BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Session is closed");
				}
			}
			catch( Exception )
			{
				throw new GDCException(BEGDC.CC.BL.Common.ErrorCode.DB_Exception, "Failed to save log infomation");
			}
		}

		public void SaveFlowInstance(ISession session, BEGDC.CC.Entity.Application App, BEGDC.CC.Entity.FlowInstance instance, string StatusFlag, string CurrentStep, string ActiveStep)
		{
			try
			{
				IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
				int typeId = utiService.GetDicItemID(this.ProjectType, BEGDC.CC.BL.Common.DicType.Application_Type);
				instance.Application = App;
				if(instance.Id>0)
				{
					instance.State = utiService.QueryStateByCode(StatusFlag);
					instance.CurrentStep = utiService.QueryStepByCode(CurrentStep, typeId);
					instance.CurrentActiveStep = utiService.QueryStepByCode(ActiveStep, typeId);
					instance.LastModifiedDate = System.DateTime.Now;
					session.Update(instance);
				}
				else
				{
					instance.State = new State();
					instance.State = utiService.QueryStateByCode(StatusFlag);
					instance.CurrentStep = new Step();
					instance.CurrentStep = utiService.QueryStepByCode(CurrentStep, typeId);
					instance.CurrentActiveStep = new Step();
					instance.CurrentActiveStep = utiService.QueryStepByCode(ActiveStep, typeId);
					instance.StartDate = System.DateTime.Now;
					instance.LastModifiedDate = System.DateTime.Now;
					session.Save(instance);
				}
			}
			catch(Exception exp)
			{
				CCS.Utility.LogAccess.WriteErrLog( exp.StackTrace, exp.Message );
				throw exp;
			}
		}

		public FlowInstance GetApplicationFlow(ISession session, int AppID )
		{
			IList list;
			try
			{
				list = session.Find("From FlowInstance as fi where fi.Application.Id="+AppID);
				if(list!=null && list.Count>0)
				{
					FlowInstance instance = list[0] as BEGDC.CC.Entity.FlowInstance;
					return instance;
				}
				else
				{
					return null;
				}
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
		}

		public BEGDC.CC.Entity.Action GetAction(ISession session, string actionName)
		{
			IList list;
			try
			{
				list = session.Find("From Action where ActionName ='"+actionName+"'");
				if(list!=null&&list.Count>0)
				{
					BEGDC.CC.Entity.Action action = list[0] as BEGDC.CC.Entity.Action;
					return action;
				}
				else
				{
					return null;
				}
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
//				session.Close();
			}	
		}

		public void SaveActionLog(ISession session, int appId, string action, string source, string target, string comment)
		{
            //ActionLog log = new ActionLog();
            //IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
            //BEGDC.CC.BL.UserManagement.IUser userService = AppContainer.Instance[ServiceConst.UserService] as BEGDC.CC.BL.UserManagement.IUser;

            //Common.Query.IQuery queryService = AppContainer.Instance[ServiceConst.QueryService] as Common.Query.IQuery;
            //Entity.Application app = queryService.GetApplication(appId);

            //int typeId = utiService.GetDicItemID(app.ApplicationType, BEGDC.CC.BL.Common.DicType.Application_Type);
            //log.Application = new Application();
            //log.Application.Id = appId;
            //log.Action = this.GetAction(session, action);
            //log.SourceStep = utiService.QueryStepByCode(source, typeId);
            //log.TargetStep = utiService.QueryStepByCode(target, typeId);
            //log.ActionDate = System.DateTime.Now;
            //log.Actor = this.CurrentOwner.Identity.Name;
            //if (((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id != ((CCIdentity)HttpContext.Current.User.Identity).ActualUserInfo.Id)
            //{
            //    log.MyBackup = userService.GetUser(((CCIdentity)HttpContext.Current.User.Identity).ActualUserInfo.NameEN);
            //}
            ////			log.MyBackup = userService.GetUser(this.CurrentOwner.Identity.Name);
            //log.Comment = comment;
            //this.SaveActionLog(session, log);

            //BEGDC.CC.BL.Common.Query.IQuery iquery = BEGDC.Utility.Castle.AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.QueryService] as BEGDC.CC.BL.Common.Query.IQuery;
            //BEGDC.CC.Entity.Application application = iquery.GetAppById(appId);

            //BEGDC.CC.BL.Common.IUtility utility = BEGDC.Utility.Castle.AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.UtilityService] as BEGDC.CC.BL.Common.IUtility;
            //BEGDC.CC.BL.Workflow.CCIdentity uid = this.CurrentOwner.Identity as BEGDC.CC.BL.Workflow.CCIdentity;
            //BEGDC.CC.Entity.OperationLog olog = new BEGDC.CC.Entity.OperationLog();
            //olog.Module = "Workflow";
            //BEGDC.CC.Entity.Employee emp = new BEGDC.CC.Entity.Employee();
            //emp.Id = uid.UserInfo.Id;
            //olog.Employee = emp;
            //olog.OperationType = log.Action.ActionName;
            //olog.AppNO = application.AppNo;
            //olog.CurrentStep = log.SourceStep.StepName;
            //olog.Time = System.DateTime.Now;
            //olog.Description = "Actor:" + log.Actor + "; SourceStep:" + log.SourceStep.StepName + "; TargetStep:" + log.TargetStep.StepName + "; SourceStep:" + log.ActionDate.Value.ToString() + "; AppNo:" + application.AppNo + "; Action: " + log.Action.ActionName;
            //utility.SaveOperationLog(olog);
            this.SaveActionLog(session, appId, action, source, target, null, comment);
		}

        public void SaveActionLog(ISession session, int appId, string action, string source, string target,FlowMember member, string comment)
        {
            ActionLog log = new ActionLog();
            IUtility utiService = AppContainer.Instance[ServiceConst.UtilityService] as IUtility;
            BEGDC.CC.BL.UserManagement.IUser userService = AppContainer.Instance[ServiceConst.UserService] as BEGDC.CC.BL.UserManagement.IUser;

            Common.Query.IQuery queryService = AppContainer.Instance[ServiceConst.QueryService] as Common.Query.IQuery;
            Entity.Application app = queryService.GetApplication(appId);

            int typeId = utiService.GetDicItemID(app.ApplicationType, BEGDC.CC.BL.Common.DicType.Application_Type);
            log.Application = new Application();
            log.Application.Id = appId;
            log.Action = this.GetAction(session, action);
            log.SourceStep = utiService.QueryStepByCode(source, typeId);
            log.TargetStep = utiService.QueryStepByCode(target, typeId);
            log.ActionDate = System.DateTime.Now;
            //changed by leo
            log.Actor = (member != null) ? member.Employee.NameEN : this.CurrentOwner.Identity.Name;
            if (member == null)
            {
                if (((CCIdentity)HttpContext.Current.User.Identity).UserInfo.Id != ((CCIdentity)HttpContext.Current.User.Identity).ActualUserInfo.Id)
                {
                    log.MyBackup = userService.GetUser(((CCIdentity)HttpContext.Current.User.Identity).ActualUserInfo.NameEN);
                }
            }
            //			log.MyBackup = userService.GetUser(this.CurrentOwner.Identity.Name);
            log.Comment = comment;
            this.SaveActionLog(session, log);

            BEGDC.CC.BL.Common.Query.IQuery iquery = BEGDC.Utility.Castle.AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.QueryService] as BEGDC.CC.BL.Common.Query.IQuery;
            BEGDC.CC.Entity.Application application = iquery.GetAppById(appId);

            BEGDC.CC.BL.Common.IUtility utility = BEGDC.Utility.Castle.AppContainer.Instance[BEGDC.CC.BL.Common.ServiceConst.UtilityService] as BEGDC.CC.BL.Common.IUtility;
            BEGDC.CC.BL.Workflow.CCIdentity uid = this.CurrentOwner.Identity as BEGDC.CC.BL.Workflow.CCIdentity;
            BEGDC.CC.Entity.OperationLog olog = new BEGDC.CC.Entity.OperationLog();
            olog.Module = "Workflow";
            BEGDC.CC.Entity.Employee emp = new BEGDC.CC.Entity.Employee();
            emp.Id = (member != null) ? member.Employee.Id : uid.UserInfo.Id;
            olog.Employee = emp;
            olog.OperationType = log.Action.ActionName;
            olog.AppNO = application.AppNo;
            olog.CurrentStep = log.SourceStep.StepName;
            olog.Time = System.DateTime.Now;
            olog.Description = "Actor:" + log.Actor + "; SourceStep:" + log.SourceStep.StepName + "; TargetStep:" + log.TargetStep.StepName + "; SourceStep:" + log.ActionDate.Value.ToString() + "; AppNo:" + application.AppNo + "; Action: " + log.Action.ActionName;
            utility.SaveOperationLog(olog);
        }

		public FlowInstance QueryFlowInstance(ISession session, long flowId)
		{
			FlowInstance instance = null;
			try
			{
				IList list = session.Find("from FlowInstance where FlowID="+flowId);
				if(list.Count > 0)
					instance = (FlowInstance)list[0];
			}
			catch(GDCException gdcEx)
			{
				CCS.Utility.LogAccess.WriteErrLog( gdcEx.StackTrace, gdcEx.Message );
				throw gdcEx;
			}
			catch(System.Data.SqlClient.SqlException sqlEx)
			{
				CCS.Utility.LogAccess.WriteErrLog( sqlEx.StackTrace, sqlEx.Message );
				throw new GDCException(ErrorCode.DB_Exception, "DB Exception", sqlEx);
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new GDCException(ErrorCode.UserService_Exception, "UserService Exception", ex);
			}
			finally
			{
//				session.Close();
			}
			
			return instance;
		}

		private long GetStepId(string stateKey)
		{
			ProcessStateList states = BEGDC.CC.BL.Workflow.Configuration.GetProcessStateList(this.ProjectType);
			for(int i=0; i < states.Count; i++)
			{
				ProcessState state = states[i];
				for(int j=0; j < state.ChildrenStates.Count; j++)
				{
					ProcessState chr = state.ChildrenStates[j];
					if (chr.Key == stateKey)
					{
						return chr.ID;
					}
				}
			}
			return 0;
		}
		private string GetDepartmentHeadByCostCenter(ISession session, string costCenter)
		{
			string head = string.Empty;
			try
			{
				string sql = "Select empl.EmployeeNo ";
				sql += "From UserRole AS ur, Employee AS empl, Role AS rl, Department de, CostCenter cc ";
				sql += "where empl.IsActived='1' and ur.EmployeeNo=empl.EmployeeNo and ur.RoleID=rl.RoleID  and rl.RoleName='DeptHead'";
				sql+= " and de.DepartmentID=cc.DepartmentID and empl.Department = de.departmentid and cc.CostCenterID='"+costCenter+"'";
				DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, sql);
				if( table.Rows.Count == 0 )
				{
					table = null;
					sql = "Select empl.EmployeeNo ";
					sql += "From UserRole AS ur, Employee AS empl, Role AS rl, Department de, CostCenter cc ";
					sql += "where empl.IsActived='1' and ur.EmployeeNo=empl.EmployeeNo and ur.RoleID=rl.RoleID  and rl.RoleName='DeptHead'";
					sql+= " and de.DepartmentID=cc.DepartmentID and empl.EmployeeNo = de.departmenthead and cc.CostCenterID='"+costCenter+"'";
					table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, sql);
				}
				if(table != null && table.Rows.Count > 0)
					head = table.Rows[0][0].ToString();
				else
					throw new GDCException("OCV_001", "Department Head has not been assigned, please contact role admin and submit again.");
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
			return head;
		}
		public string GetCostCenterHeadByCostCenter(ISession session, string costCenter)
		{
			string head = string.Empty;
			try
			{
				string sql = "Select empl.EmployeeNo ";
				sql += "From UserRole AS ur, Employee AS empl, Role AS rl, CostCenterHead cd, DicItem di ";
				sql += "where empl.IsActived='1' and ur.EmployeeNo=empl.EmployeeNo and ur.RoleID=rl.RoleID  and rl.RoleName='CostCenterHead'";
				sql+= " and ur.userroleid=cd.userroleid and cd.costcenterid = di.dicitemid and di.DicItemKey='"+costCenter+"'";
				DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, sql);
				if(table != null && table.Rows.Count > 0)
					head = table.Rows[0][0].ToString();
				else
					throw new GDCException("OCV_002", "CostCenter head has not been assigned, please contact role admin and submit again.");
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new Exception("Execute error.", ex);
			}
			finally
			{
			}
			return head;
		}
		public string GetDepartmentFNCByDepartment(ISession session, string depart)
		{
			string head = string.Empty;
			try
			{
//				string sql = "Select empl.EmployeeNo ";
//				sql += "From UserRole AS ur, Employee AS empl, Role AS rl, Department de ";
//				sql += "where empl.IsActived='1' and ur.EmployeeNo=empl.EmployeeNo and ur.RoleID=rl.RoleID  and rl.RoleName='FNC'";
//				sql+= " and de.DepartmentID=empl.Department and de.DepartmentCode='"+depart+"'";
				
				string sql = "Select empl.EmployeeNo AS EmployeeNo, empl.NameEN AS Name ";
				sql += "From UserRole AS ur, Employee AS empl, Role AS rl, FNCForDepartment fd, department d ";
				sql += "where empl.IsActived='1' and ur.EmployeeNo=empl.EmployeeNo and ur.RoleID=rl.RoleID  and rl.RoleName='"+BEGDC.CC.BL.Workflow.UserRole.FNC+"'";
				sql+= " and d.departmentid = fd.DepartmentID and d.DepartmentCode='"+depart+"' and ur.UserRoleID = fd.UserRoleID";

				DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, sql);
				if(table != null && table.Rows.Count > 0)
					head = table.Rows[0][0].ToString();
				else
					throw new GDCException("OCV_003", "Department FNC has not been assigned, please contact role admin and submit again.");
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
			return head;
		}

		public string GetSSMEHead(ISession session)
		{
			string head = string.Empty;
			try
			{
				string sql = "Select empl.EmployeeNo ";
				sql += "From UserRole AS ur, Employee AS empl, Role AS rl ";
				sql += "where empl.IsActived='1' and ur.EmployeeNo=empl.EmployeeNo and ur.RoleID=rl.RoleID  and rl.RoleName='SSMEHead'";
				DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, sql);
				if(table != null && table.Rows.Count > 0)
					head = table.Rows[0][0].ToString();
				else
					throw new GDCException("OCV_004", "SSME head has not been assigned, please contact role admin and submit again.");
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
			return head;
		}

		private string GetDepartmentHeadByDepartment(ISession session, string depart)
		{
			string head = string.Empty;
			try
			{
				string sql = "Select empl.EmployeeNo ";
				sql += "From UserRole AS ur, Employee AS empl, Role AS rl, Department de ";
				sql += "where empl.IsActived='1' and ur.EmployeeNo=empl.EmployeeNo and ur.RoleID=rl.RoleID  and rl.RoleName='DeptHead'";
				sql+= " and de.DepartmentID=empl.Department and de.DepartmentCode='"+depart+"'";
				DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, sql);
				
				if( table.Rows.Count == 0 )
				{
					table = null;
					sql = "Select empl.EmployeeNo ";
					sql += "From UserRole AS ur, Employee AS empl, Role AS rl, Department de ";
					sql += "where empl.IsActived='1' and ur.EmployeeNo=empl.EmployeeNo and ur.RoleID=rl.RoleID  and rl.RoleName='DeptHead'";
					sql+= " and de.departmenthead=empl.EmployeeNo and de.DepartmentCode='"+depart+"'";
					table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute(session, sql);

				}
				if(table != null && table.Rows.Count > 0)
					head = table.Rows[0][0].ToString();
				else
					throw new GDCException("OCV_001", "Department Head has not been assigned, please contact role admin and submit again.");

			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw ex;
			}
			finally
			{
			}
			return head;
		}
		#endregion

		#region Check writable step
		
		public bool CheckWritableStep(ISession session, int appId, string stepName)
		{
			bool isWritable = true;
			try
			{

				string cmdText = "SELECT Step.StepCode FROM FlowInstance fi INNER JOIN Step ON fi.CurrentStep = Step.StepID WHERE fi.AppID=" + appId;
				DataTable table = BEGDC.Utility.NHibernate.NHibernateUtil.Execute( session, cmdText );
				if( (table == null || table.Rows.Count == 0) && stepName == "Request" )
				{
					isWritable = true;
				}
				else if( table != null && table.Rows.Count > 0 )
				{
					if( table.Rows[0][0].ToString() == stepName )
					{
						isWritable = true;
					}
					else
					{
						isWritable = false;
					}
				}
			}
			catch(Exception ex)
			{
				CCS.Utility.LogAccess.WriteErrLog( ex.StackTrace, ex.Message );throw new GDCException(ErrorCode.DB_Exception, ex.Message, ex);
			}
			
			return isWritable;
		}

		#endregion

		private string _currentState;
		/// <summary>
		/// Current State
		/// </summary>
		public string CurrentState
		{
			get
			{
				return this._currentState;
			}
			set
			{
				this._currentState = value;
			}
		}

		private string _comment;
		/// <summary>
		/// Comment
		/// </summary>
		public string Comment
		{
			get
			{
				return this._comment;
			}
			set
			{
				this._comment = value;
			}
		}

		/// <summary>
		/// Current Owner
		/// </summary>
		public IPrincipal CurrentOwner
		{
			get
			{
				return System.Web.HttpContext.Current.User;
			}
		}

	}
}
